package service

import (
	"context"
	"crypto/md5"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"path/filepath"
	"strings"
	"time"

	"go-file-perception-model/internal/model"
	"go-file-perception-model/internal/repository"
	"go-file-perception-model/pkg/vector"
)

// DirectoryManager 目录管理器
type DirectoryManager struct {
	fileMonitorRepo repository.FileMonitorRepository
	vectorDB        vector.VectorDB
	activeDirectory *model.DirectoryMonitorRecord
}

// NewDirectoryManager 创建目录管理器实例
func NewDirectoryManager(fileMonitorRepo repository.FileMonitorRepository, vectorDB vector.VectorDB) *DirectoryManager {
	return &DirectoryManager{
		fileMonitorRepo: fileMonitorRepo,
		vectorDB:        vectorDB,
	}
}

// GenerateDirectoryID 生成目录ID
func (m *DirectoryManager) GenerateDirectoryID(directoryPath string) string {
	// 使用目录路径的MD5哈希作为ID的一部分
	hasher := md5.New()
	hasher.Write([]byte(directoryPath))
	hashBytes := hasher.Sum(nil)
	hashString := hex.EncodeToString(hashBytes)
	
	// 取前8个字符作为ID
	return fmt.Sprintf("dir_%s", hashString[:8])
}

// GenerateCollectionName 生成集合名称
func (m *DirectoryManager) GenerateCollectionName(directoryPath string) string {
	// 使用目录路径的SHA256哈希作为集合名称，确保唯一性
	hasher := sha256.New()
	hasher.Write([]byte(directoryPath))
	hashBytes := hasher.Sum(nil)
	hashString := hex.EncodeToString(hashBytes)
	
	// 使用哈希值的前16个字符作为集合名称，确保足够的唯一性
	return fmt.Sprintf("col_%s", hashString[:16])
}

// RegisterDirectory 注册目录
func (m *DirectoryManager) RegisterDirectory(directoryPath string) (*model.DirectoryMonitorRecord, error) {
	// 移除目录路径中可能存在的引号
	cleanPath := directoryPath
	if len(cleanPath) >= 2 && strings.HasPrefix(cleanPath, "\"") && strings.HasSuffix(cleanPath, "\"") {
		cleanPath = cleanPath[1 : len(cleanPath)-1]
	}
	
	// 检查目录是否已存在
	existingRecord, err := m.fileMonitorRepo.GetDirectoryRecordByPath(cleanPath)
	if err != nil {
		return nil, fmt.Errorf("failed to check existing directory: %w", err)
	}
	
	if existingRecord != nil {
		return existingRecord, nil
	}
	
	// 生成目录ID和集合名称
	directoryID := m.GenerateDirectoryID(cleanPath)
	collectionName := m.GenerateCollectionName(cleanPath)
	
	// 获取目录名称
	directoryName := filepath.Base(cleanPath)
	
	// 创建目录记录
	now := time.Now()
	record := &model.DirectoryMonitorRecord{
		ID:             directoryID,
		DirectoryPath:  cleanPath,
		DirectoryName:  directoryName,
		CollectionName: collectionName,
		IsMonitoring:   false,
		LastScanTime:   now,
		LastIndexedTime: now,
		TotalFiles:     0,
		IndexedFiles:   0,
		CreatedAt:      now,
		UpdatedAt:      now,
	}
	
	// 保存到数据库
	if err := m.fileMonitorRepo.CreateDirectoryRecord(record); err != nil {
		return nil, fmt.Errorf("failed to create directory record: %w", err)
	}
	
	// 创建向量数据库集合（仅当vectorDB可用时）
	if m.vectorDB != nil {
		ctx := context.Background()
		vectorSize := 768 // BGE-base-zh的向量维度
		
		if err := m.vectorDB.CreateCollection(ctx, collectionName, vectorSize); err != nil {
			// 如果集合创建失败，删除目录记录
			_ = m.fileMonitorRepo.DeleteDirectoryRecord(directoryID)
			return nil, fmt.Errorf("failed to create vector collection: %w", err)
		}
	}
	
	return record, nil
}

// UnregisterDirectory 注销目录
func (m *DirectoryManager) UnregisterDirectory(directoryPath string) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 删除目录相关的所有数据
	if err := m.fileMonitorRepo.DeleteDirectoryRecord(record.ID); err != nil {
		return fmt.Errorf("failed to delete directory record: %w", err)
	}
	
	// 注意：这里不删除向量数据库集合，因为可能还有其他用途
	// 如果需要删除集合，可以调用 vectorDB 的删除集合方法
	
	return nil
}

// GetDirectoryRecord 获取目录记录
func (m *DirectoryManager) GetDirectoryRecord(directoryPath string) (*model.DirectoryMonitorRecord, error) {
	return m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
}

// ListAllDirectories 列出所有目录
func (m *DirectoryManager) ListAllDirectories() ([]*model.DirectoryMonitorRecord, error) {
	return m.fileMonitorRepo.ListAllDirectoryRecords()
}

// SetActiveDirectory 设置活动目录
func (m *DirectoryManager) SetActiveDirectory(directoryPath string) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 设置向量数据库的活动集合（仅当vectorDB可用时）
	if m.vectorDB != nil {
		m.vectorDB.SetCollection(record.CollectionName)
	}
	
	// 保存活动目录引用
	m.activeDirectory = record
	
	return nil
}

// GetActiveDirectory 获取活动目录
func (m *DirectoryManager) GetActiveDirectory() (*model.DirectoryMonitorRecord, error) {
	if m.activeDirectory != nil {
		return m.activeDirectory, nil
	}
	
	// 如果没有设置活动目录，尝试获取第一个目录作为活动目录
	records, err := m.fileMonitorRepo.ListAllDirectoryRecords()
	if err != nil {
		return nil, fmt.Errorf("failed to list directories: %w", err)
	}
	
	if len(records) == 0 {
		return nil, fmt.Errorf("no directories found")
	}
	
	// 使用第一个目录作为活动目录
	m.activeDirectory = records[0]
	// 设置向量数据库的活动集合（仅当vectorDB可用时）
	if m.vectorDB != nil {
		m.vectorDB.SetCollection(records[0].CollectionName)
	}
	
	return m.activeDirectory, nil
}

// UpdateDirectoryStats 更新目录统计信息
func (m *DirectoryManager) UpdateDirectoryStats(directoryPath string, totalFiles, indexedFiles int) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 更新统计信息
	record.TotalFiles = totalFiles
	record.IndexedFiles = indexedFiles
	record.UpdatedAt = time.Now()
	
	// 保存更新
	return m.fileMonitorRepo.UpdateDirectoryRecord(record)
}

// UpdateDirectoryMonitoringStatus 更新目录监控状态
func (m *DirectoryManager) UpdateDirectoryMonitoringStatus(directoryPath string, isMonitoring bool) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 更新监控状态
	record.IsMonitoring = isMonitoring
	record.UpdatedAt = time.Now()
	
	// 保存更新
	return m.fileMonitorRepo.UpdateDirectoryRecord(record)
}

// UpdateDirectoryLastIndexedTime 更新目录最后索引时间
func (m *DirectoryManager) UpdateDirectoryLastIndexedTime(directoryPath string) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 更新最后索引时间
	record.LastIndexedTime = time.Now()
	record.UpdatedAt = time.Now()
	
	// 保存更新
	return m.fileMonitorRepo.UpdateDirectoryRecord(record)
}

// UpdateDirectoryLastScanTime 更新目录最后扫描时间
func (m *DirectoryManager) UpdateDirectoryLastScanTime(directoryPath string) error {
	// 获取目录记录
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	// 更新最后扫描时间
	record.LastScanTime = time.Now()
	record.UpdatedAt = time.Now()
	
	// 保存更新
	return m.fileMonitorRepo.UpdateDirectoryRecord(record)
}

// IsDirectoryRegistered 检查目录是否已注册
func (m *DirectoryManager) IsDirectoryRegistered(directoryPath string) (bool, error) {
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return false, fmt.Errorf("failed to get directory record: %w", err)
	}
	
	return record != nil, nil
}

// GetDirectoryCollectionName 获取目录的集合名称
func (m *DirectoryManager) GetDirectoryCollectionName(directoryPath string) (string, error) {
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return "", fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return "", fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	return record.CollectionName, nil
}

// GetDirectoryID 获取目录ID
func (m *DirectoryManager) GetDirectoryID(directoryPath string) (string, error) {
	record, err := m.fileMonitorRepo.GetDirectoryRecordByPath(directoryPath)
	if err != nil {
		return "", fmt.Errorf("failed to get directory record: %w", err)
	}
	
	if record == nil {
		return "", fmt.Errorf("directory not found: %s", directoryPath)
	}
	
	return record.ID, nil
}